package derivable;

import operator.EqualsOperator;
import operator.LessThanOperator;
import operator.NegativeEqualsOperator;
import operator.Operator;
import variable.Variable;

public class Proposition implements Derivable<Proposition> {
	private Variable x;
	private Variable y;
	private Operator operator;
	private boolean negated;

	public Proposition(final Variable x, final Operator operator, final Variable y, final boolean negated) {
		this.x = x;
		this.y = y;
		this.operator = operator;
		this.negated = negated;
	}
	public static Proposition create(final String x, final String op, final String y, final boolean b) {
		final Variable varx = new Variable(x);
		final Variable vary = new Variable(y);
		Operator operator;
		switch (op) {
		case "=":
			operator = new EqualsOperator();
			break;
		case "<":
			operator = new LessThanOperator();
			break;
		case "-=":
			operator = new NegativeEqualsOperator();
			break;
		default:
			throw new IllegalArgumentException();
		}
		return new Proposition(varx, operator, vary, b);
	}
	@Override
	public boolean derives(final Proposition o) {
		return equals(o);
	}
	@Override
	public boolean equals(final Object obj) {
		if (obj.getClass() == Proposition.class) {
			final boolean x = getX().equals(((Proposition) obj).getX());
			final boolean y = getY().equals(((Proposition) obj).getY());
			final boolean op = getOperator().equals(((Proposition) obj).getOperator());
			final boolean neg = isNegated() == ((Proposition) obj).isNegated();
			if (getOperator().getClass() == EqualsOperator.class) {
				final boolean changeX = getX().equals(((Proposition) obj).getY());
				final boolean changeY = getY().equals(((Proposition) obj).getX());
				return ((x && y) || (changeX && changeY)) && op && neg;
			}
			return x && y && op && neg;
		}
		return false;
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = (prime * result) + (negated ? 1231 : 1237);
		result = (prime * result) + ((operator == null) ? 0 : operator.hashCode());
		result = (prime * result) + ((x == null) ? 0 : x.hashCode());
		result = (prime * result) + ((y == null) ? 0 : y.hashCode());
		return result;
	}
	public Variable getX() {
		return x;
	}
	public Variable getY() {
		return y;
	}
	public Operator getOperator() {
		return operator;
	}
	public boolean isNegated() {
		return negated;
	}
	public void setX(final Variable x) {
		this.x = x;
	}
	public void setY(final Variable y) {
		this.y = y;
	}
	public void setOperator(final Operator operator) {
		this.operator = operator;
	}
	public void setNegated(final boolean negated) {
		this.negated = negated;
	}
}
